<template>
  <div class="base64-encoder">
    <h1 class="title">Base64 字符串编码/解码</h1>
    <p class="description">将字符串编码和解码为Base64格式</p>

    <div class="encoder-container">
      <!-- URL安全编码说明 -->
      <div class="url-safe-info">
        <a-alert type="info" show-icon message="URL安全编码说明" description="标准的Base64包含 + / = 三个字符，在URL中这些字符需要被转义。开启URL安全编码后，会将 + 替换为 -，/ 替换为 _，并移除 = 号，使结果可以直接用于URL。" />
      </div>

      <!-- 左侧编码区域 -->
      <div class="encode-section">
        <h2>字符串转换为Base64</h2>
        <div class="url-safe-option">
          <span class="switch-label">URL安全编码：</span>
          <a-switch v-model:checked="isUrlSafeEncode" :checked-children="'开'" :un-checked-children="'关'" />
        </div>
        <a-textarea v-model:value="rawText" placeholder="请输入字符串" :auto-size="{ minRows: 5, maxRows: 10 }" class="input-area" @keydown.stop />
        <div class="result-area">
          <a-textarea v-model:value="encodedText" placeholder="Base64编码结果" :auto-size="{ minRows: 5, maxRows: 10 }" readonly @keydown.stop />
          <a-button type="primary" class="copy-btn" :disabled="!encodedText" @click="copyToClipboard(encodedText)"> 复制Base64 </a-button>
        </div>
      </div>

      <!-- 右侧解码区域 -->
      <div class="decode-section">
        <h2>Base64转换为字符串</h2>
        <div class="url-safe-option">
          <span class="switch-label">URL安全解码：</span>
          <a-switch v-model:checked="isUrlSafeDecode" :checked-children="'开'" :un-checked-children="'关'" />
        </div>
        <a-textarea v-model:value="base64Text" placeholder="请输入Base64字符串" :auto-size="{ minRows: 5, maxRows: 10 }" class="input-area" @keydown.stop />
        <div class="result-area">
          <a-textarea v-model:value="decodedText" placeholder="解码结果" :auto-size="{ minRows: 5, maxRows: 10 }" readonly @keydown.stop />
          <a-button type="primary" class="copy-btn" :disabled="!decodedText" @click="copyToClipboard(decodedText)"> 复制解码结果 </a-button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue'
import { message } from 'ant-design-vue'

// 响应式状态
const rawText = ref('')
const encodedText = ref('')
const base64Text = ref('')
const decodedText = ref('')
const isUrlSafeEncode = ref(false)
const isUrlSafeDecode = ref(false)

// 监听原始文本变化，自动进行编码
watch(rawText, (newValue) => {
  if (!newValue) {
    encodedText.value = ''
    return
  }
  try {
    const encoded = btoa(unescape(encodeURIComponent(newValue)))
    encodedText.value = isUrlSafeEncode.value ? encoded.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '') : encoded
  } catch (error) {
    message.error('编码失败：无效的输入')
    encodedText.value = ''
  }
})

// 监听Base64文本变化，自动进行解码
watch(base64Text, (newValue) => {
  if (!newValue) {
    decodedText.value = ''
    return
  }
  try {
    let processedInput = newValue
    if (isUrlSafeDecode.value) {
      processedInput = processedInput
        .replace(/-/g, '+')
        .replace(/_/g, '/')
        .padEnd(processedInput.length + ((4 - (processedInput.length % 4)) % 4), '=')
    }
    decodedText.value = decodeURIComponent(escape(atob(processedInput)))
  } catch (error) {
    message.error('解码失败：无效的Base64字符串')
    decodedText.value = ''
  }
})

// 复制到剪贴板
const copyToClipboard = async (text) => {
  try {
    await navigator.clipboard.writeText(text)
    message.success('复制成功')
  } catch (error) {
    message.error('复制失败')
  }
}
</script>

<style scoped>
.base64-encoder {
  padding: 20px;
  max-width: 1200px;
  margin: 0 auto;
}

.title {
  text-align: center;
  margin-bottom: 10px;
}

.description {
  text-align: center;
  color: rgba(0, 0, 0, 0.45);
  margin-bottom: 30px;
}

.encoder-container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}

.encode-section,
.decode-section {
  background: #fff;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.03);
  border: 1px solid #f0f0f0;
}

h2 {
  margin-bottom: 15px;
  font-size: 1.2em;
  color: rgba(0, 0, 0, 0.85);
}

.url-safe-option {
  margin-bottom: 15px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.switch-label {
  color: rgba(0, 0, 0, 0.85);
  font-size: 14px;
}

.input-area {
  margin-bottom: 15px;
}

.result-area {
  position: relative;
}

.copy-btn {
  margin-top: 10px;
}

@media (max-width: 768px) {
  .encoder-container {
    grid-template-columns: 1fr;
  }
}

.url-safe-info {
  grid-column: 1 / -1;
  margin-bottom: 20px;
}
</style>
